// 模板
// Created by Administrator on 2025/6/16.
// 这里 typename 和 class 可以混用

#include <iostream>
#include <vector>
using namespace std;

/**
 * 函数模板
 *
 */

/**
 * template 定义模板的关键字
 * typename 表示这是个类型参数，T是占位符类型名称，编辑器会根据调用时传入的参数类型自动推导出实际类型，此处 typename 和 class 作用相同
 * inline 内联函数，编辑器会自动将函数代码复制到调用处，减少函数调用的开销，适用于简单逻辑的函数
 * @param a 常量的引用，不能修改原始数据，也避免了拷贝，提高性能
 * @param b
 * @return
 */
template<typename T> // 模板参数声明
inline T const &Max(T const &a, T const &b) {
    return a > b ? a : b;
}

void funcTemplateFunc() {
    int i = 39;
    int j = 20;
    // 调用 int Max(int i,int j)
    cout << Max(i, j) << endl;

    double d1 = 13.5;
    double d2 = 20.7;
    cout << Max(d1, d2) << endl;

    string s1 = "Hello";
    string s2 = "World";
    cout << Max(s1, s2) << endl;
}


/**
 * 类模板
 * template<class T> 和 template<typename T> 功能相同，表示模板参数声明
 *
 */

template<class T>
class Stack {
private:
    // 元素
    vector<T> elems;

public:
    // 插入元素
    void push(T const &);

    // 删除元素
    void pop();

    // 返回栈顶元素
    T top() const;

    // 判断栈是否为空
    bool empty() const {
        return elems.empty();
    }
};

template<class T>
void Stack<T>::push(T const &elem) {
    // 追加元素
    elems.push_back(elem);
}

template<class T>
void Stack<T>::pop() {
    if (empty()) {
        throw out_of_range("移除失败，elems为空");
    }
    // 移除尾部的元素
    elems.pop_back();
}

template<class T>
T Stack<T>::top() const {
    if (empty()) {
        throw out_of_range("移除失败，elems为空");
    }
    // 返回尾部最后一个元素
    return elems.back();
}

void classFunc() {
    Stack<int> intStack;
    Stack<string> strStack;
    try {
        intStack.push(999);
        cout << "intStack value:" << intStack.top() << endl;

        strStack.push("helloworld");
        cout << "strStack value:" << strStack.top() << endl;

        strStack.pop();
        strStack.pop(); // 容器为空，移除失败，抛出异常
    } catch (exception const &ex) {
        cerr << "error:" << ex.what() << endl;
    }
}

/**
 * 模板函数重载
 */

template<typename T1, typename T2>
void print(const T1 &a, const T2 &b) {
    cout << "1、内容1为：\t" << to_string(a) << "内容2为：\t" << to_string(b) << endl;
}

template<typename T>
void print(const T &a, const T &b) {
    cout << "2、内容1为：\t" << to_string(a) << "内容2为：\t" << to_string(b) << endl;
}

template<typename T>
void print(const T &a) {
    cout << "3、内容为：\t" << to_string(a) << endl;
}


void templateOverloadingFunc() {
    int a = 1;
    int b = 2;
    double c = 3.14;

    print(a, c); // 重载函数1
    print(a, a); // 重载函数2
    print(c); // 重载函数3
}

int main(int argc, char *argv[]) {
    // funcTemplateFunc();
    // classFunc();
    templateOverloadingFunc();
    return 0;
}
